﻿// 临界数据脏.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <Windows.h>

/*
多个线程同时访问临界数据，导致临界数据脏：
    临界数据脏是指数据在特定条件下的状态，可能会导致系统出现异常或错误的情况。这种情况通常发生在数据处理的边界或者临界条件处，例如当数据达到最大值或最小值时，或者当数据发生变化时。
    在这些情况下，数据可能会出现错误或不一致的状态，从而导致系统出现问题。因此，在开发应用程序或系统时，需要特别关注临界数据的处理，以确保系统能够正确处理这些数据。

*/
/*
我们通常把解决  多个线程同时访问一块区域的这种问题 称为 线程同步：
		核心思想： 都是把时间错开

		用户态：api层面就解决掉问题，不需要调用内核代码
			用户态的解决方案：
				原子锁：
						原子锁是一种多线程编程中的同步机制，用于保证多个线程对共享资源的互斥访问。它是一种原子操作，即在执行期间不能被中断或分割，保证了操作的完整性和一致性。
						原子锁可以保证同一时刻只有一个线程能够访问共享资源，其他线程需要等待锁被释放才能继续执行。常见的原子锁有互斥锁和读写锁。
					最小的 叫 原子 （不可分割）
					把某个行为设置为原子行为 （不可分割）

					字节 最小管理单位

					原子操作的函数：
						InterlockedIncrement   ++	将 (作为原子操作的指定 32 位变量的值增加一) 递增。

					volatile  关键字
					让编译器不优化

						int n = 666;
						int* p = &n;
						*p == 666


					//物理寄存器的地址
					#define  Addr     volatile *(int*)0xabcdfafa
					Addr = 123;

*/

int n = 0;
void f()
{
    for (int i = 0; i < 50000000; i++)
    {
		InterlockedIncrement((volatile unsigned long long*) & n);	//将 (作为原子操作的指定 32 位变量的值增加一) 递增。
        //n++;
    }
}
int main()
{
    //创建线程：     
    HANDLE h1 =  CreateThread(NULL, NULL,
        (LPTHREAD_START_ROUTINE)f,
        NULL, NULL, NULL);

    HANDLE h2 = CreateThread(NULL, NULL,
        (LPTHREAD_START_ROUTINE)f,
        NULL, NULL, NULL);

    WaitForSingleObject(h1, INFINITE);
    WaitForSingleObject(h2, INFINITE);

    printf("n:%d\n", n);        //没有任何方案的话，n最终的值不可能是100000000；


    return 0;
}


